export enum TokenType {
    IDENTIFIER,
    NUMBER,
    STRING,
    OPERATOR,
    DOT,
    COMMA,
    LEFT_PAREN,
    RIGHT_PAREN,
    LEFT_BRACKET,
    RIGHT_BRACKET,
    WHITESPACE
}

export interface IToken {
    type: TokenType;
    value: string;
}

export type AstNodeType =
    | 'Identifier'
    | 'MemberExpression'
    | 'CallExpression'
    | 'BinaryExpression'
    | 'LogicalExpression'
    | 'NumericLiteral'
    | 'StringLiteral'
    | 'BooleanLiteral'
    | 'NullLiteral'
    | 'LambdaExpression'
    | 'UnaryExpression'
    | 'MethodCallExpression';

export interface BaseNode {
    type: AstNodeType;
}

export interface IdentifierNode extends BaseNode {
    type: 'Identifier';
    name: string;
}

export interface MemberExpressionNode extends BaseNode {
    type: 'MemberExpression';
    object: IAstNode;
    property: IAstNode;
    computed: boolean;
}

export interface CallExpressionNode extends BaseNode {
    type: 'CallExpression';
    callee: IAstNode;
    arguments: IAstNode[];
}

export interface BinaryExpressionNode extends BaseNode {
    type: 'BinaryExpression';
    operator: string;
    left: IAstNode;
    right: IAstNode;
}

export interface LogicalExpressionNode extends BaseNode {
    type: 'LogicalExpression';
    operator: string;
    left: IAstNode;
    right: IAstNode;
}

export interface NumericLiteralNode extends BaseNode {
    type: 'NumericLiteral';
    value: number;
}

export interface StringLiteralNode extends BaseNode {
    type: 'StringLiteral';
    value: string;
}

export interface BooleanLiteralNode extends BaseNode {
    type: 'BooleanLiteral';
    value: boolean;
}

export interface NullLiteralNode extends BaseNode {
    type: 'NullLiteral';
}

export interface LambdaExpressionNode extends BaseNode {
    type: 'LambdaExpression';
    parameters: IdentifierNode[];
    body: IAstNode;
}

export interface UnaryExpressionNode extends BaseNode {
    type: 'UnaryExpression';
    operator: string;
    argument: IAstNode;
}

export interface MethodCallExpressionNode extends BaseNode {
    type: 'MethodCallExpression';
    object: IAstNode;
    methodName: string;
    arguments: IAstNode[];
}

export type IAstNode =
    | IdentifierNode
    | MemberExpressionNode
    | CallExpressionNode
    | BinaryExpressionNode
    | LogicalExpressionNode
    | NumericLiteralNode
    | StringLiteralNode
    | BooleanLiteralNode
    | NullLiteralNode
    | LambdaExpressionNode
    | UnaryExpressionNode
    | MethodCallExpressionNode;

export class ExpressionParser {
    private expression: string;
    private position: number;
    private tokens: IToken[];
    private currentToken: IToken | null;

    constructor() {
        this.expression = '';
        this.position = 0;
        this.tokens = [];
        this.currentToken = null;
    }

    public parse(expression: string): IAstNode {
        if (!expression.trim()) {
            throw new Error('表达式不能为空');
        }

        this.expression = expression;
        this.position = 0;
        this.tokens = this.tokenize();
        this.position = 0; // 重置位置以便解析
        return this.parseExpression();
    }

    private tokenize(): IToken[] {
        const tokens: IToken[] = [];
        this.position = 0;

        while (this.position < this.expression.length) {
            const char = this.expression[this.position];

            // 处理空白字符
            if (/\s/.test(char)) {
                let value = '';
                while (this.position < this.expression.length && /\s/.test(this.expression[this.position])) {
                    value += this.expression[this.position];
                    this.position++;
                }
                tokens.push({ type: TokenType.WHITESPACE, value });
                continue;
            }

            // 处理标识符
            if (/[a-zA-Z_]/.test(char)) {
                let value = '';
                while (this.position < this.expression.length && /[a-zA-Z0-9_]/.test(this.expression[this.position])) {
                    value += this.expression[this.position];
                    this.position++;
                }
                tokens.push({ type: TokenType.IDENTIFIER, value });
                continue;
            }

            // 处理数字
            if (/[0-9]/.test(char)) {
                let value = '';
                while (this.position < this.expression.length && /[0-9.]/.test(this.expression[this.position])) {
                    value += this.expression[this.position];
                    this.position++;
                }
                tokens.push({ type: TokenType.NUMBER, value });
                continue;
            }

            // 处理字符串
            if (char === '"' || char === "'") {
                const quote = char;
                let value = '';
                this.position++; // 跳过开始引号
                while (this.position < this.expression.length && this.expression[this.position] !== quote) {
                    value += this.expression[this.position];
                    this.position++;
                }
                if (this.position >= this.expression.length) {
                    throw new Error('字符串未闭合');
                }
                this.position++; // 跳过结束引号
                tokens.push({ type: TokenType.STRING, value });
                continue;
            }

            // 处理运算符
            const operators = ['&&', '||', '==', '!=', '<=', '>=', '=>', '+', '-', '*', '/', '%', '!', '<', '>'];
            let matched = false;

            // 先尝试匹配双字符运算符
            for (const op of operators) {
                if (op.length === 2 && this.expression.startsWith(op, this.position)) {
                    tokens.push({ type: TokenType.OPERATOR, value: op });
                    this.position += 2;
                    matched = true;
                    break;
                }
            }

            if (matched) continue;

            // 再尝试匹配单字符运算符
            for (const op of operators) {
                if (op.length === 1 && this.expression[this.position] === op) {
                    tokens.push({ type: TokenType.OPERATOR, value: op });
                    this.position++;
                    matched = true;
                    break;
                }
            }

            if (matched) continue;

            // 处理其他字符
            switch (char) {
                case '.':
                    tokens.push({ type: TokenType.DOT, value: '.' });
                    break;
                case '(':
                    tokens.push({ type: TokenType.LEFT_PAREN, value: '(' });
                    break;
                case ')':
                    tokens.push({ type: TokenType.RIGHT_PAREN, value: ')' });
                    break;
                case ',':
                    tokens.push({ type: TokenType.COMMA, value: ',' });
                    break;
                case '[':
                    tokens.push({ type: TokenType.LEFT_BRACKET, value: '[' });
                    break;
                case ']':
                    tokens.push({ type: TokenType.RIGHT_BRACKET, value: ']' });
                    break;
                default:
                    throw new Error(`无效的字符: ${char} at position ${this.position}`);
            }
            this.position++;
        }

        return tokens;
    }

    private moveToNextToken(): void {
        this.position++;
        this.currentToken = this.tokens[this.position] || null;
    }

    private parseExpression(): IAstNode {
        let left = this.parsePrimary();

        while (this.position < this.tokens.length) {
            const token = this.tokens[this.position];

            // 跳过空白字符
            if (token.type === TokenType.WHITESPACE) {
                this.position++;
                continue;
            }

            // 处理成员访问
            if (token.type === TokenType.DOT) {
                this.position++; // 跳过点号
                if (this.position >= this.tokens.length ||
                    this.tokens[this.position].type !== TokenType.IDENTIFIER) {
                    throw new Error('点号后必须是标识符');
                }
                const property = this.tokens[this.position];
                this.position++; // 跳过属性名

                left = {
                    type: 'MemberExpression',
                    object: left,
                    property: { type: 'Identifier', name: property.value },
                    computed: false
                };

                // 检查是否是方法调用
                if (this.position < this.tokens.length &&
                    this.tokens[this.position].type === TokenType.LEFT_PAREN) {
                    const args = this.parseArguments();
                    left = {
                        type: 'CallExpression',
                        callee: left,
                        arguments: args
                    };
                }
            }
            // 处理数组访问
            else if (token.type === TokenType.LEFT_BRACKET) {
                this.position++; // 跳过左方括号
                const index = this.parseExpression();
                if (this.position >= this.tokens.length ||
                    this.tokens[this.position].type !== TokenType.RIGHT_BRACKET) {
                    throw new Error('缺少右方括号');
                }
                this.position++; // 跳过右方括号

                left = {
                    type: 'MemberExpression',
                    object: left,
                    property: index,
                    computed: true
                };
            }
            // 处理方法调用
            else if (token.type === TokenType.LEFT_PAREN) {
                const args = this.parseArguments();
                left = {
                    type: 'CallExpression',
                    callee: left,
                    arguments: args
                };
            }
            // 处理二元运算符
            else if (token.type === TokenType.OPERATOR) {
                const operator = token.value;
                this.position++; // 跳过运算符

                // 处理逻辑运算符
                if (operator === '&&' || operator === '||') {
                    const right = this.parseExpression();
                    left = {
                        type: 'LogicalExpression',
                        operator: operator,
                        left: left,
                        right: right
                    };
                }
                // 处理其他二元运算符
                else {
                    const right = this.parsePrimary();
                    left = {
                        type: 'BinaryExpression',
                        operator: operator,
                        left: left,
                        right: right
                    };
                }
            }
            else {
                break;
            }
        }

        return left;
    }

    private parseArguments(): IAstNode[] {
        const args: IAstNode[] = [];
        this.position++; // 跳过左括号

        // 跳过空白字符
        while (this.position < this.tokens.length &&
            this.tokens[this.position].type === TokenType.WHITESPACE) {
            this.position++;
        }

        // 处理空参数列表
        if (this.position < this.tokens.length &&
            this.tokens[this.position].type === TokenType.RIGHT_PAREN) {
            this.position++; // 跳过右括号
            return args;
        }

        while (this.position < this.tokens.length) {
            // 跳过空白字符
            while (this.position < this.tokens.length &&
                this.tokens[this.position].type === TokenType.WHITESPACE) {
                this.position++;
            }

            if (this.position >= this.tokens.length) {
                throw new Error('缺少右括号');
            }

            // 解析参数
            const arg = this.parseExpression();
            args.push(arg);

            // 跳过空白字符
            while (this.position < this.tokens.length &&
                this.tokens[this.position].type === TokenType.WHITESPACE) {
                this.position++;
            }

            if (this.position >= this.tokens.length) {
                throw new Error('缺少右括号');
            }

            const token = this.tokens[this.position];
            if (token.type === TokenType.RIGHT_PAREN) {
                this.position++; // 跳过右括号
                break;
            } else if (token.type === TokenType.COMMA) {
                this.position++; // 跳过逗号
                // 跳过空白字符
                while (this.position < this.tokens.length &&
                    this.tokens[this.position].type === TokenType.WHITESPACE) {
                    this.position++;
                }
                // 检查逗号后是否直接跟着右括号
                if (this.position < this.tokens.length &&
                    this.tokens[this.position].type === TokenType.RIGHT_PAREN) {
                    throw new Error('参数列表不能以逗号结尾');
                }
            } else {
                throw new Error('参数之间需要逗号分隔');
            }
        }

        if (this.position > this.tokens.length ||
            (this.position === this.tokens.length &&
                this.tokens[this.position - 1].type !== TokenType.RIGHT_PAREN)) {
            throw new Error('缺少右括号');
        }

        return args;
    }

    private parsePrimary(): IAstNode {
        if (this.position >= this.tokens.length) {
            throw new Error('表达式不完整');
        }

        // 跳过空白字符
        while (this.position < this.tokens.length &&
            this.tokens[this.position].type === TokenType.WHITESPACE) {
            this.position++;
        }

        if (this.position >= this.tokens.length) {
            throw new Error('表达式不完整');
        }

        const token = this.tokens[this.position];

        switch (token.type) {
            case TokenType.IDENTIFIER: {
                this.position++;
                let name = token.value;

                // 检查是否是泛型类型
                if (this.position < this.tokens.length &&
                    this.tokens[this.position].value === '<') {
                    name += '<';
                    this.position++;

                    // 跳过空白字符
                    while (this.position < this.tokens.length &&
                        this.tokens[this.position].type === TokenType.WHITESPACE) {
                        this.position++;
                    }

                    // 解析泛型参数
                    while (this.position < this.tokens.length) {
                        const paramToken = this.tokens[this.position];
                        if (paramToken.value === '>') {
                            name += '>';
                            this.position++;
                            break;
                        }
                        name += paramToken.value;
                        this.position++;
                    }

                    if (!name.endsWith('>')) {
                        throw new Error('泛型类型未闭合');
                    }
                }

                // 检查是否是特殊关键字
                switch (name) {
                    case 'true':
                        return { type: 'BooleanLiteral', value: true };
                    case 'false':
                        return { type: 'BooleanLiteral', value: false };
                    case 'null':
                        return { type: 'NullLiteral' };
                    default:
                        // 检查是否是 Lambda 表达式
                        if (this.position < this.tokens.length &&
                            this.tokens[this.position].type === TokenType.OPERATOR &&
                            this.tokens[this.position].value === '=>') {
                            this.position++; // 跳过 '=>'
                            const body = this.parseExpression();
                            return {
                                type: 'LambdaExpression',
                                parameters: [{ type: 'Identifier', name }],
                                body
                            };
                        }
                        return { type: 'Identifier', name };
                }
            }
            case TokenType.NUMBER:
                this.position++;
                return { type: 'NumericLiteral', value: Number(token.value) };
            case TokenType.STRING:
                this.position++;
                return { type: 'StringLiteral', value: token.value };
            case TokenType.LEFT_PAREN: {
                this.position++;
                const expr = this.parseExpression();
                if (this.position >= this.tokens.length ||
                    this.tokens[this.position].type !== TokenType.RIGHT_PAREN) {
                    throw new Error('缺少右括号');
                }
                this.position++;
                return expr;
            }
            case TokenType.OPERATOR: {
                // 处理一元运算符
                if (token.value === '+' || token.value === '-' || token.value === '!') {
                    this.position++;
                    const operand = this.parsePrimary();
                    return {
                        type: 'UnaryExpression',
                        operator: token.value,
                        argument: operand
                    };
                }
                // 其他运算符作为二元运算符处理
                return this.parseExpression();
            }
            default:
                throw new Error(`无效的表达式: ${token.value}`);
        }
    }
} 